﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NBusiness.Data.Testing.Mocks;
using NBusiness.Data;
using NBusiness.Query;
using NBusiness.Data.Providers.SqlServer.Query;

namespace Testing
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class ModelBaseTests
    {
        public ModelBaseTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestFetch()
        {
            MockModel actual = null;
            MockModel.Fetch(1, m => actual = m);

            MockDatabaseProvider provider = (MockDatabaseProvider)Settings.Instance.GetSetting(SettingsType.Provider, typeof(MockModel));

            Assert.IsNotNull(actual);
            Assert.AreEqual(2, MethodCall.Calls.Count);
            Assert.AreEqual("Execute", MethodCall.Calls[0].Method);
            Assert.AreEqual("LoadModel", MethodCall.Calls[1].Method);

            Assert.IsTrue(MethodCall.Calls[0].Values.ContainsKey("query"));

            IQuery query = MethodCall.Calls[0].Values["query"] as IQuery;
            Assert.IsNotNull(query);
            Assert.AreEqual("SELECT * FROM [Mock] AS [A] WHERE ([A].[Id]=1)", query.ToSql());

            Assert.IsTrue(MethodCall.Calls[1].Values.ContainsKey("loader"));
        }

        [TestMethod]
        public void TestInsert()
        {
            MockModel model = new MockModel();
            model.Name = "testinsert";
            model.Save();

            MockDatabaseProvider provider = (MockDatabaseProvider)Settings.Instance.GetSetting(SettingsType.Provider, typeof(MockModel));
            
            Assert.AreEqual(4, MethodCall.Calls.Count);
            Assert.AreEqual("ValidateFields", MethodCall.Calls[0].Method);
            Assert.AreEqual("InsertModel", MethodCall.Calls[1].Method);
            Assert.AreEqual("Execute", MethodCall.Calls[2].Method);
            Assert.AreEqual("InsertModelLoad", MethodCall.Calls[3].Method);

            Assert.IsTrue(MethodCall.Calls[1].Values.ContainsKey("query"));
            IQuery query = MethodCall.Calls[1].Values["query"] as IQuery;
            Assert.IsNotNull(query);
            string expected = "INSERT INTO [Mock] ([Name]) VALUES (@Name)\r\nGO";
            string actual = query.ToSql();
            Assert.AreEqual(expected, actual);

            IList<IParameterValue> parameters = ((query as SqlQuery).Statements[0] as IInsert).Parameters;
            Assert.AreEqual(2, parameters.Count);
            Assert.AreEqual("@Id", parameters[0].Name);
            Assert.AreEqual(100, parameters[0].Value);
            Assert.AreEqual(ParameterValueDirection.Output, parameters[0].Direction);

            Assert.AreEqual("@Name", parameters[1].Name);
            Assert.AreEqual("testinsert", parameters[1].Value);
            Assert.AreEqual(ParameterValueDirection.Input, parameters[1].Direction);
        }
    }
}
